﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.ComponentModel;
using LibrarySync2.Common.Xml;
using LibrarySync2.Common.Enum;
using LibrarySync2.Common.Event;
using LibrarySync2.Common.Interfaces;
using LibrarySync2.Common.Extensions;
using System.Xml.Schema;
using System.Xml;
using System.Xml.XPath;

namespace LibrarySync2.Business.FileSystem.Item
{
    public abstract class FileSystemItemBase : IFileSystemItem
    {
        public string Name { get; set; }
        public string FullName { get; set; }
        public string Root { get; set; }

        public string RelativePath
        {
            get { return FullName.Substring(Root.Length); }
        }

        public List<IFileSystemItem> Children { get; set; }

        public FileSystemItemBase()
        {
            Children = new List<IFileSystemItem>();
        }

        public override bool Equals(object obj)
        {
            if (obj == null)
                throw new ArgumentNullException("obj");
            var compareObj = obj as FileSystemItemBase;
            if (compareObj == null)
                return base.Equals(obj);

            return this.RelativePath.Equals(compareObj.RelativePath, StringComparison.OrdinalIgnoreCase);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        #region IXmlSerializable Members

        public XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            var document = new XmlDocument();
            document.Load(reader);
            ReadElementsFromXml(document.SelectSingleNode("//Item"));
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteStartElement("Item");
            WriteElementsToXml(writer);
            writer.WriteEndElement();
        }

        protected virtual void WriteElementsToXml(XmlWriter writer)
        {
            writer.WriteElementString("Name", Name);
            writer.WriteElementString("FullName", FullName);
            writer.WriteElementString("Root", Root);
            writer.WriteStartElement("Children");
            foreach (IFileSystemItem child in Children)
            {
                writer.WriteStartElement("Child");
                writer.WriteAttributeString("Type", child.GetType().FullName);
                child.WriteXml(writer);
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
        }

        protected virtual void ReadElementsFromXml(XmlNode itemNode)
        {
            Name = itemNode.GetNodeValue("Name");
            FullName = itemNode.GetNodeValue("FullName");
            Root = itemNode.GetNodeValue("Root");

            var childNodes = itemNode.SelectNodes("Children/Child");
            foreach (XmlNode childNode in childNodes)
            {
                var typeString = childNode.GetNodeAttributeValue("Type");
                var childItemXml = childNode.InnerXml;

                var childType = Type.GetType(typeString);
                var childItem = childType.Instantiate<IFileSystemItem>();

                using (var childReader = new XmlTextReader(new StringReader(childItemXml)))
                {
                    childItem.ReadXml(childReader);
                }

                Children.Add(childItem);
            }
        }

        #endregion
    }
}
